"""
LangChain 异步流式输出示例

本代码演示如何使用LangChain构建异步流式处理链：
1. 加载环境变量配置API密钥
2. 初始化大语言模型并启用流式输出
3. 构建处理链：提示词 -> 模型 -> 输出解析器
4. 使用异步流式输出实时获取生成结果

关键概念：
- 异步编程：使用async/await提高并发性能
- 流式输出：实时获取模型生成内容，提升用户体验
- LCEL（LangChain Expression Language）：使用管道操作符组合组件
- 输出解析器：处理模型返回结果的结构化输出
"""

import asyncio
import os

from dotenv import load_dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 自动加载 .env 文件中的环境变量 - 用于配置API密钥等敏感信息
load_dotenv()


# 异步主函数 - 使用async定义异步函数
async def main():
    # 初始化ChatOpenAI模型 - 配置模型参数和流式输出
    llm = ChatOpenAI(api_key=os.getenv("MODELSCOPE_API_KEY"), openai_api_base=os.getenv("MODELSCOPE_API_BASE"), model="deepseek-ai/DeepSeek-R1-0528", streaming=True, temperature=0.7)


    # 创建聊天提示模板 - 定义用户输入的模板结构
    prompt = ChatPromptTemplate.from_template(
        "给我讲一个关于{topic}的笑话？要超过400个字"  # 模板包含{topic}变量占位符
    )

    # 初始化字符串输出解析器 - 将模型输出转换为字符串格式
    parser = StrOutputParser()

    # 使用LCEL（LangChain表达式语言）构建处理链
    # 管道操作符 | 连接三个组件：提示词 -> 模型 -> 输出解析器
    chain = prompt | llm | parser

    # 异步流式输出处理 - 实时获取模型生成内容
    print("=== 开始流式生成 ===")
    async for chuck in chain.astream({"topic": "飞机"}):
        # 实时输出每个chunk，| 作为分隔符便于观察流式过程
        # flush=True确保立即输出不缓冲，end="|"用|代替换行作为分隔符
        print(chuck, end="|", flush=True)
    print("\n=== 流式生成结束 ===")


# 程序入口点 - 运行异步主函数
if __name__ == "__main__":
    asyncio.run(main())  # 启动异步事件循环并运行main函数
